home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1992 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- static char RCSid[] = "$Id: child.c,v 5.2 1993/01/23 02:04:02 panos Exp $" ;
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <syslog.h>
-
- #include "str.h"
-
- #include "options.h"
-
- #include "attr.h"
- #include "server.h"
- #include "state.h"
-
- char *inet_ntoa() ;
-
- void msg() ;
- void msg_suspend() ;
- void msg_resume() ;
-
- /*
- * This function is invoked in a forked process to run a server.
- * If the service is internal the appropriate function is invoked
- * otherwise the server is exec'ed.
- * This functions also logs the remote user id if appropriate
- */
- void child_process( serp )
- register struct server *serp ;
- {
- register struct service_config *scp = CONF( SERVER_SERVICE( serp ) ) ;
- void signal_default_state() ;
- void rename_process() ;
- void set_credentials() ;
- void exec_server() ;
- void log_remote_user() ;
-
- #ifdef DEBUG_SERVER
- if ( debug.on )
- {
- msg( LOG_DEBUG, "child_process", "Process %d is sleeping", getpid() ) ;
- sleep( 10 ) ;
- }
- #endif
-
- if ( ! IS_INTERCEPTED( scp ) )
- {
- set_credentials( scp ) ;
- signal_default_state() ;
- }
-
- if ( serp->log_remote_user )
- log_remote_user( serp ) ;
-
- if ( ! IS_INTERNAL( scp ) )
- exec_server( serp ) ;
- else
- {
- char name[ 180 ] ;
-
- /*
- * NOTE: We don't bother to disassociate from the controlling terminal
- * (we have a controlling terminal only if debug.on is TRUE)
- *
- * Also, for interceptor processes, we give them the name:
- * interceptor service-id
- */
- if ( IS_INTERCEPTED( scp ) )
- strx_print( INT_NULL, name, sizeof( name ),
- "%s %s interceptor", program_name, scp->id ) ;
- else
- {
- int namelen = sizeof( name ) - 1 ; /* leave space for the NUL */
- struct sockaddr_in *sinp = conn_address( SERVER_CONNECTION( serp ) ) ;
- int len = strx_nprint( name, namelen,
- "(%s service) %s", program_name, scp->id ) ;
-
- if ( ACCEPTS_CONNECTIONS( scp ) && sinp != SOCKADDRIN_NULL )
- strx_print( INT_NULL, &name[ len ], namelen - len,
- " %s", inet_ntoa( sinp->sin_addr ) ) ;
- }
- rename_process( name ) ;
- (*SERVER_SERVICE( serp )->builtin->function)( serp ) ;
- }
- _exit( 0 ) ;
- /* NOTREACHED */
- }
-
-
- PRIVATE void exec_server( serp )
- struct server *serp ;
- {
- struct service_config *scp = CONF( SERVER_SERVICE( serp ) ) ;
- int fd ;
- int descriptor = SERVER_FD( serp ) ;
- char *func = "exec_server" ;
- void no_control_tty() ;
-
- if ( debug.on )
- msg( LOG_DEBUG, func, "duping %d", descriptor ) ;
-
- for ( fd = 0 ; fd <= 2 ; fd++ )
- if ( dup2( descriptor, fd ) == -1 )
- {
- msg( LOG_ERR, func,
- "dup2( %d, %d ) failed: %m", descriptor, fd ) ;
- _exit( 1 ) ;
- }
-
- (void) close( descriptor ) ;
-
- if ( debug.on )
- {
- msg( LOG_DEBUG, func,
- "exec( %s ). no control terminal", scp->server ) ;
- no_control_tty() ;
- }
-
- #ifdef RLIMIT_NOFILE
- {
- struct rlimit rl ;
-
- rl.rlim_cur = ps.ros.orig_max_descriptors ;
- rl.rlim_max = ps.ros.max_descriptors ;
- (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
- }
- #endif
-
- msg_suspend() ;
-
- (void) execve( scp->server, scp->server_argv,
- env_getvars( ENV( scp )->env ) ) ;
-
- /*
- * The exec failed. Log the error and exit.
- */
- msg_resume() ;
- msg( LOG_ERR, func, "execv( %s ) failed: %m", scp->server ) ;
- _exit( 0 ) ;
- }
-
-
- /*
- * Rename this process by changing the ps.ros.Argv vector
- * Try to put the name of the service in ps.ros.Argv[0], Argv[1]
- * until either the service name is exhausted or we run out
- * of ps.ros.Argv's.
- * The rest of ps.ros.Argv is cleared to spaces
- */
- PRIVATE void rename_process( name )
- char *name ;
- {
- register char *from = name ;
- register char *to = ps.ros.Argv[ 0 ] ;
- register int index = 1 ;
-
- while ( *from != NUL )
- {
- if ( *to != NUL )
- *to++ = *from++ ;
- else
- if ( index < ps.ros.Argc )
- to = ps.ros.Argv[ index++ ] ;
- else
- break ;
- }
- str_fill( to, ' ' ) ;
- while ( index < ps.ros.Argc )
- str_fill( ps.ros.Argv[ index++ ], ' ' ) ;
- }
-
-
- PRIVATE void set_credentials( scp )
- register struct service_config *scp ;
- {
- char *func = "set_credentials" ;
-
- if ( SPECIFIED( scp, A_GROUP ) || SPECIFIED( scp, A_USER ) )
- if ( ps.ros.is_superuser )
- {
- int gid = SPECIFIED( scp, A_GROUP ) ? scp->gid : scp->user_gid ;
-
- if ( setgid( gid ) == -1 )
- {
- msg( LOG_ERR, func, "setgid failed: %m" ) ;
- _exit( 1 ) ;
- }
- }
- else
- msg( LOG_WARNING, func, "can't change gid; not superuser" ) ;
-
- if ( SPECIFIED( scp, A_USER ) )
- if ( ps.ros.is_superuser )
- {
- if ( setuid( scp->uid ) == -1 )
- {
- msg( LOG_ERR, func, "setuid failed: %m" ) ;
- _exit( 1 ) ;
- }
- }
- else
- msg( LOG_WARNING, func, "can't change uid; not superuser" ) ;
- }
-
-